package org.l.mybatis.core.handler;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.reflect.FieldUtils;
import org.l.mybatis.core.annotation.DBTable;

/**
 * Created by 严秋旺 on 2017/8/2.
 */
public class ObjectHandler {

    private static Map<Class<?>, ObjectHandler> caches = new HashMap<>();

    private Class<?> type;
    private String tableName;
    private List<FieldHandler> dbFields = new ArrayList<>();
    private List<FieldHandler> primaryFields = new ArrayList<>();
    private List<FieldHandler> allFields = new ArrayList<>();
    private Map<String, FieldHandler> dbNameMapHandler = new HashMap<>();

    private ObjectHandler(Class<?> type) {
        this.type = type;
    }

    public static ObjectHandler create(Class<?> type) {
        ObjectHandler objectHandler = caches.get(type);

        if (objectHandler == null) {
            objectHandler = new ObjectHandler(type);
            objectHandler.parse();
            caches.put(type, objectHandler);
        }

        return objectHandler;
    }

    /**
     * 对象解析
     */
    private void parse() {
        parseTable();
        parseField();
    }

    private void parseTable() {
        DBTable dbTable = this.type.getAnnotation(DBTable.class);

        if (dbTable == null) {
            this.tableName = this.type.getSimpleName();
        } else {
            this.tableName = dbTable.value();
        }
    }

    private void parseField() {
        List<Field> fields = FieldUtils.getAllFieldsList(this.type);

        for (Field field : fields) {
            if (!isIncludable(field))
                continue;

            FieldHandler handler = new FieldHandler(this.type, field);
            allFields.add(handler);
            dbNameMapHandler.put(handler.getDbName(), handler);

            if (handler.isPrimary()) {
                primaryFields.add(handler);
            } else {
                dbFields.add(handler);
            }
        }
    }

    private boolean isIncludable(Field field) {
        int modifier = field.getModifiers();

        if (Modifier.isStatic(modifier)) {
            return false;
        }

        return true;
    }

    /**
     * 获取表名
     * @return
     */
    public String getTableName() {
        return this.tableName;
    }

    public Class<?> getType() {
        return type;
    }

    /**
     * 获取所有非主键字段
     *
     * @return
     */
    public List<FieldHandler> getDbFields() {
        return dbFields;
    }

    /**
     * 获取所有主键字段
     * @return
     */
    public List<FieldHandler> getPrimaryFields() {
        return primaryFields;
    }

    /**
     * 获取所有字段
     * @return
     */
    public List<FieldHandler> getAllFields() {
        return allFields;
    }

    /**
     * 根据数据字段名获取FieldHandler
     * @param name
     * @return
     */
    public FieldHandler getFieldHandlerByDbField(String name) {
        return dbNameMapHandler.get(name);
    }

}
